﻿using Ly.EBussiness.Core.Dto.User;
using Ly.EBussiness.Core.Manager.Dto.LoginDto;
using Ly.EBussiness.EntityFrameworkCore;
using Ly.EBussiness.EntityFrameworkCore.Entity;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Domain.Services;

namespace Ly.EBussiness.Core.Manager;

/// <summary>
/// 
/// </summary>
public class LoginManager : DomainService
{
    private readonly EBussinessDbContext _dbContext;
    private readonly IReadOnlyQueryRepository _readOnlyQueryRepository;

    private const string AppId = "wx738e16dc897365e5";
    private const string AppSecret = "e367c4c0c95a9095ed58416f314648c4";

    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbContext"></param>
    /// <param name="readOnlyQueryRepository"></param>
    public LoginManager(EBussinessDbContext dbContext, IReadOnlyQueryRepository readOnlyQueryRepository)
    {
        _dbContext = dbContext;
        _readOnlyQueryRepository = readOnlyQueryRepository;
    }

    public async Task<LoginResult> LoginAsync(UserLoginInput input)
    {
        var weChatSessionResponse = await GetSessionKeyAsync(input.Code);
        var userInfo =
            await _readOnlyQueryRepository.FirstOrDefaultAsync<UserInfo>(new { UserId = weChatSessionResponse.OpenId });
        if (userInfo is null)
        {
            userInfo = (await _dbContext.UserInfos.AddAsync(new UserInfo() { UserId = weChatSessionResponse.OpenId }))
                .Entity;
            await _dbContext.SaveChangesAsync();
        }

        return new LoginResult().LoginSuccess(UserInfoDto.MapperUserInfoDto(userInfo));
    }

    public async Task<WeChatSessionResponse> GetSessionKeyAsync(string jsCode)
    {
        if (string.IsNullOrEmpty(jsCode)) throw new BusinessException("501",$"入参为空: jsCode");
        using var httpClient = new HttpClient();
        var response = await httpClient.GetAsync(
            $"https://api.weixin.qq.com/sns/jscode2session?appid={AppId}&secret={AppSecret}&js_code={jsCode}&grant_type=authorization_code");
        var content = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"Failed to get session key: {content}");
        }

        var result = JsonConvert.DeserializeObject<WeChatSessionResponse>(content);
        if (result is null || result?.Errcode != 0)
        {
            throw new BusinessException("1001",$"Error from WeChat API: {result.Errmsg}");
        }

        return result;
    }
}

public class WeChatSessionResponse
{
    public string OpenId { get; set; }

    public string SessionKey { get; set; }

    public int Errcode { get; set; }

    public string Errmsg { get; set; }
}